from flask import get_flashed_messages, request, flash, render_template, redirect, url_for, session
from models.usuario import metadata, Usuario
from models.database import db_session
from models.solicitudCambio import SolicitudCambio
import sys
import datetime
from models.faseManager import FaseManager
from models.estadoFaseManager import EstadoFaseManager
from models.proyectoManager import ProyectoManager
from models.estadoProyectoManager import EstadoProyectoManager
from models.estadoSCManager import EstadoSCManager
from models.solicitudCambioManager import SolicitudCambioManager
from models.usuarioManager import UsuarioManager
from models.itemManager import ItemManager
from models.votosComite import VotosComite
from models.votosComiteManager import VotosComiteManager
from models.lineaBaseManager import LineaBaseManager

faseMgr = FaseManager()
proyectoMgr = ProyectoManager()
usuarioMgr = UsuarioManager()
itemMgr= ItemManager()
estadofaseMgr = EstadoFaseManager()
estadopytoMgr = EstadoProyectoManager()
estadoSCMgr = EstadoSCManager()
solicitudMgr = SolicitudCambioManager()
votosMgr = VotosComiteManager()
lineaBaseMgr= LineaBaseManager()

"""
Clase que contiene los metodos relacionados con la inicializacion y finalizacion de proyectos
"""
        
def generarSolicitud():
    """ Metodo encargado de generar una solicitud de cambio """
    if request.method == "POST":
        fecha = request.form["fecha"]
        observacion = request.form["observacion"]
        idproyecto = session['idproyecto']
        proyecto = proyectoMgr.getProyecto(idproyecto)
        idfase = request.form["idfase"]
        iditems = request.form.getlist("items")
        estadosc = estadoSCMgr.getEstadoSC(3)
        username = session['username']
        usuario = usuarioMgr.getUsuarioFiltradoPorUser(username)
        comite = proyectoMgr.getComiteDelProyecto(idproyecto)
        codigo = "SC-"+ str(solicitudMgr.getNumeroSolicitudDelProyecto(idproyecto))
        solicitud = SolicitudCambio(codigo, fecha, observacion, 0, 0)
        solicitud.estadosc = estadosc
        solicitud.usuario = usuario
        solicitud.comite = comite
        items =[]
        b=0
        for i in xrange(0, len(iditems)):
            item = itemMgr.getItem(iditems[i])
            items.append(item)
        solicitud.items=items
        solicitudMgr.guardarSolicitudCambio(solicitud)
        return redirect(url_for("generarSolicitud", idfase=idfase))
    else:
        if session['idfase']:
            idfase = session['idfase']
            itemsAux = faseMgr.getFase(idfase).items
            items=[]
            for it in itemsAux:
                if it.idestadoitem==4 and it.idusuariohabilitado==None:
                    items.append(it)
            
            fecha = datetime.date.today()
            return render_template("generarSolicitud.html",items=items, fecha=fecha, idfase=idfase)
        else:
            if session['idproyecto']:
                flash(u"Seleccionar una fase del proyecto antes de realizar la operaci\u00f3n", "error")
            else:
                flash(u"Seleccionar un proyecto antes de realizar la operaci\u00f3n", "error")
            return redirect(url_for("configurarFase", action= "generarSolicitud"))

def antesGenerarSolicitud():
    if request.method=="POST":
        iditems = request.form.getlist("check")
         
        items=[]
        for iditem in iditems:
            items.append(itemMgr.getItem(iditem))
    #obtener los hijos de los hijos
        descendientes=[]
        for item in items:
            descendientes.append(item)
        for item in items:
            obtenerDescendientes(descendientes, item)
        
        costo=0
        for descendiente in descendientes:
            costo=costo+descendiente.costo
    #obtener todos los padres
        ascendientes=[]
        for item in items:
            ascendientes.append(item)
        for item in items:
            obtenerAscendientes(ascendientes, item)
        
        costoHundido=0
        for ascendiente in ascendientes:
            costoHundido=costoHundido+ascendiente.costo
        
    
        complejidad=0 
        for descendiente in descendientes:
            complejidad=complejidad+descendiente.complejidad
        fecha = request.form["fecha"]
        observacion = request.form["observacion"]
        return render_template("antesGenerarSolicitud.html", items= items, lista= descendientes, 
                               costo=costo, complejidad=complejidad, fecha=fecha, 
                               costoHundido= costoHundido, observacion=observacion)        
        
def obtenerDescendientes(descendientes, item):
    if item:
        for hijo in item.hijos:
            if hijo.item2 not in descendientes:
                descendientes.append(hijo.item2)
        for hijo in item.hijos:
            obtenerDescendientes(descendientes, hijo.item2)
            
        
def obtenerAscendientes(ascendientes, item):
    if item:
        for padre in item.padres:
            if padre.item1 not in ascendientes:
                ascendientes.append(padre.item1)
        for padre in item.padres:
            obtenerAscendientes(ascendientes, padre.item1)
           


def gestionarSolicitud():
    """ Metodo encargado de la interfaz principal de aprobacion de solicitudes de cambio"""
    filtro=""
    if request.method == "POST":
        if request.form["operacion"] != "":
            operacion = request.form["operacion"]
            idproyecto = request.form["idproyecto"]
            return redirect(url_for(operacion, idproyecto=idproyecto)) 
        else:
            idproyecto = request.form["idproyecto"]
            return render_template("gestionarSolicitud.html", idproyecto=idproyecto)
    if request.method == "GET":    
        if session['idproyecto']:
            idproyecto = session['idproyecto']
            proyecto = proyectoMgr.getProyecto(idproyecto)
            return render_template("gestionarSolicitud.html", proyecto= proyecto, idproyecto= idproyecto)
        else:
            flash(u"Seleccionar un proyecto antes de realizar la operaci\u00f3n", "error")
            return redirect(url_for("configurarProyecto", action = "gestionarSolicitud"))
        
def listarSolicitudes():
    """ Metodo encargado de listar las solicitudes de cambio de un proyecto """
    filtro=""
    if request.method == "POST":
        idproyecto = request.form["idproyecto"]
        filtro = request.form["filtro"]
        proyecto = proyectoMgr.getProyecto(idproyecto)
        return paginarSolicitudes(idproyecto, proyecto, 1, filtro)
    if request.method == "GET":
        if request.args.getlist("filtro"):
            filtro = request.args.getlist("filtro")[0]
        idproyecto = request.args.getlist("idproyecto")[0]
        pagina = 1
        if request.args.getlist("pagina"):
            pagina = request.args.getlist("pagina")[0]
        proyecto = proyectoMgr.getProyecto(idproyecto)
        return paginarSolicitudes(idproyecto, proyecto,pagina , filtro) 

def consultarDetalleSolicitud():
    """ Metodo encargado de consultar los datos de una solicitud """
    
    if request.method == "GET":
        idsolicitud = request.args.getlist("idsolicitud")[0]    
        solicitud = solicitudMgr.getSolicitudCambio(idsolicitud)
        items = solicitud.items
        usuarioVotos=[]
        for votos in solicitud.votos:
            usuarioVotos.append(votos.integrante)    
        descendientes=[]
        for item in items:
            descendientes.append(item)
        for item in items:
            obtenerDescendientes(descendientes, item)
        costo=0
        for descendiente in descendientes:
            costo=costo+descendiente.costo
        ascendientes=[]
        for item in items:
            ascendientes.append(item)
        for item in items:
            obtenerAscendientes(ascendientes, item)
        costoHundido=0
        for ascendiente in ascendientes:
            costoHundido=costoHundido+ascendiente.costo
        complejidad=0 
        for descendiente in descendientes:
            complejidad=complejidad+descendiente.complejidad
        fecha = solicitud.fecha
        observacion = solicitud.observacion
        return render_template("consultarDetalleSolicitud.html",usuarioVotos=usuarioVotos, fecha=fecha, observacion=observacion,
                items=items , idproyecto= request.args.getlist("idproyecto")[0], complejidad=complejidad,
                solicitud = solicitud, costoHundido=costoHundido, costo=costo, descendientes=descendientes)
    else:
        idproyecto = request.form["idproyecto"]
        return redirect(url_for("listarSolicitudes", idproyecto=idproyecto))       
        
def votarSolicitud():      
    """ Metodo encargado de listar las solicitudes de un proyecto """
    
    if request.method == "GET":
        idproyecto = request.args.getlist("idproyecto")[0]
        proyecto = proyectoMgr.getProyecto(idproyecto)
        solicitudes = proyectoMgr.getSolicitudesDelProyecto(idproyecto)
        solicitudesPendientes = []
        username = session['username']
        usuario = usuarioMgr.getUsuarioFiltradoPorUser(username)
        comite = proyectoMgr.getComiteDelProyecto(idproyecto)
        integrantes = comite.usuarios
        aux=0
        for integrante in integrantes:
            if integrante.idusuario == usuario.idusuario:
                aux=1
        for solicitud in solicitudes:
            if solicitud.estadosc.idestadosc == 3 and aux == 1:
                solicitudesPendientes.append(solicitud)
        return render_template("votarSolicitud.html", proyecto=proyecto, solicitudes = solicitudesPendientes, idproyecto = idproyecto)
    return redirect(url_for("gestionarSolicitud")) 

def generarInforme():     
    """ Metodo encargado de votar (aprobar/rechazar) la solitud de cambio (incluye la visualizacion del informe) """
    
    if request.method == "GET":
        if request.args.getlist("idvoto"):
            idproyecto=request.args.getlist("idproyecto")[0]
            idsolicitud = request.args.getlist("idsolicitud")[0]
            username = session['username']
            usuario = usuarioMgr.getUsuarioFiltradoPorUser(username)
            solicitud = solicitudMgr.getSolicitudCambio(idsolicitud)
            idvoto = request.args.getlist("idvoto")[0]
            yaVoto = votosMgr.usuarioYaVoto(solicitud.idsolicitud,usuario.idusuario)
            if yaVoto:
                
                flash("El usuario ya voto a esta solicitud de cambio")
            else:
                if idvoto == "1":
                     solicitud.votos_a_favor = solicitud.votos_a_favor + 1
                     voto = VotosComite(voto="SI")
                elif idvoto == "2":
                    solicitud.votos_en_contra = solicitud.votos_en_contra + 1
                    voto = VotosComite(voto="NO")
                voto.integrante = usuario
                voto.solicitud = solicitud
                votosMgr.guardarVoto(voto)
                totalVotos = solicitud.votos_en_contra + solicitud.votos_a_favor
                comite = solicitud.comite
                estadoSolicitudApr = estadoSCMgr.getEstadoSC(1)
                estadoSolicitudRec = estadoSCMgr.getEstadoSC(1)
                # verifica la cantidad de votos para saber si todos ya votaron, etc
                # falta que ser cambie el estado de los items, etc si la solicitud se aprueba
                if (totalVotos == comite.cant_comite):
                    if (solicitud.votos_a_favor > solicitud.votos_en_contra):
                        solicitud.estadosc = estadoSolicitudApr # la solicitud se aprueba
                        items= solicitud.items
                        #abrir fases
                        nroFase= items[0].fase.numero
                        fases = items[0].fase.proyecto.fases
                        for fase in fases:
                            #poner en revision las fases siguientes menos la que esta abierta
                            if fase.numero >= nroFase and fase.idestadofase !=2:
                                fase.idestadofase=4
                                faseMgr.guardarFase(fase)
                             
                        descendientes=[]
                        #Se autoriza al usuario la modificacion de los items d ela solicitud
                        for item in items:
                            item.usuarioHabilitado=solicitud.usuario
                        for item in items:
                            descendientes.append(item)
                        for item in items:
                            obtenerDescendientes(descendientes, item)
                        #Se les pone en revision tanto a los items de la solicitud como a todos los afectados
                        for descendiente in descendientes:
                            descendiente.idestadoitem=3
                            itemMgr.guardarItem(descendiente)
                        #obtiene las lineas base de los items afectados
                        lineasBase=[]
                        for item in descendientes:
                            if item.lineaBase:
                                if item.lineaBase not in lineasBase:
                                    lineasBase.append(item.lineaBase)
                        #Cambia el estado de los items de cada lineaBase        
                        for linea in lineasBase:
                            itemsEnLinea=linea.items
                            linea.idestadolb=4
                            lineaBaseMgr.guardarLineaBase(linea)      
                            for itemDeLinea in itemsEnLinea:
                                itemDeLinea.idestadoitem=3
                                itemMgr.guardarItem(itemDeLinea)
                          
                        session["_flashes"]=[]
                        flash("Solicitud aprobada, puede modificar su/s item/s")
                        
                    else:
                        solicitud.estadosc = estadoSolicitudRec # la solicitud se rechaza
                # se almacena el voto del usuario
                solicitudMgr.guardarSolicitudCambio(solicitud)                
            return redirect(url_for("votarSolicitud", idproyecto=idproyecto, solicitud=solicitud))
        
        else:
            idsolicitud = request.args.getlist("idsolicitud")[0]
            solicitud = solicitudMgr.getSolicitudCambio(idsolicitud)
            items = solicitud.items
            usuarioVotos=[]
            for votos in solicitud.votos:
                usuarioVotos.append(votos.integrante)
            descendientes=[]
            for item in items:
                descendientes.append(item)
            for item in items:
                obtenerDescendientes(descendientes, item)
            
            costo=0
            for descendiente in descendientes:
                costo=costo+descendiente.costo
            ascendientes=[]
            for item in items:
                ascendientes.append(item)
            for item in items:
                obtenerAscendientes(ascendientes, item)
            
            costoHundido=0
            for ascendiente in ascendientes:
                costoHundido=costoHundido+ascendiente.costo
            
            complejidad=0 
            for descendiente in descendientes:
                complejidad=complejidad+descendiente.complejidad
            fecha = solicitud.fecha
            observacion = solicitud.observacion
            return render_template("generarInforme.html", usuarioVotos=usuarioVotos, fecha=fecha, observacion=observacion,
                    items=items , idproyecto= request.args.getlist("idproyecto")[0], complejidad=complejidad,
                    solicitud = solicitud, costoHundido=costoHundido, costo=costo, descendientes=descendientes)
    else:
        idproyecto = request.form["idproyecto"]
        return redirect(url_for("votarSolicitud", idproyecto=idproyecto))    

def paginarSolicitudes(idproyecto, proyecto, pagina, filtro):
    """ Metodo encargado de la paginacion de solicitudes a partir de un filtro """
    porPagina= 5
    pagina = int(pagina)
    total = solicitudMgr.getSolicitudesPaginado(idproyecto, nombre=filtro, desde=None, hasta=None)
    if total % porPagina == 0:
        cantPaginas= total/porPagina
    else:
        resto = total % porPagina
        subtotal = (total-resto)
        cantPaginas= (subtotal/porPagina) + 1
    hasta = pagina * porPagina
    desde = hasta - porPagina
    sc = solicitudMgr.getSolicitudesPaginado(idproyecto, filtro, desde, hasta)
    return render_template("listarSolicitudes.html", lista = sc, idproyecto = idproyecto, proyecto =proyecto,\
        filtro = filtro, form=request.form, primera=1, ultima= cantPaginas, ant= pagina-1,\
        sig=pagina +1, cantPaginas = cantPaginas, pagina = pagina)


